#pragma once
#include "common.hpp"
#include "addr.hpp"
#include "log.hpp"
#include "thread.hpp"
#include "threadpool.hpp"
#include "dict.hpp"
using namespace td;
const int delfd = -1;
const int lislen = 10;
using func_t = function<string(const string, inetaddr)>;
using task_t = function<void()>;
class tcpserver : public nocopy
{

public:
    tcpserver(uint16_t port, func_t func) : _port(port), _isrunning(0), _listensockfd(delfd), _func(func) {}
    void init()
    {
        // 1·创建监听套接字：
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0); // 面向字节流
        if (_listensockfd < 0)
        {
            use_log(loglevel::DEBUG) << "socket failure!";
            exit(SOCKET_ERR);
        }
        use_log(loglevel::DEBUG) << "socket success!";
        // 2·进行套接字绑定主机：
        inetaddr addr(_port);
        int n = bind(_listensockfd, (sockaddr *)addr.addrptr(), addr.addrlen());
        if (n < 0)
        {
            use_log(loglevel::DEBUG) << "bind failure!";
            exit(BIND_ERR);
        }
        use_log(loglevel::DEBUG) << "bind success!";

        // 3·进行监听操作（监听_listensockfd文件里发送信息的队列成员）
        int m = listen(_listensockfd, lislen); // 监听队列可以存放connect的客户端
        if (m < 0)
        {
            use_log(loglevel::DEBUG) << " listen failure!";
            exit(LISTEN_ERR);
        }
        use_log(loglevel::DEBUG) << "listen success!";
    }
    void service(int sd, inetaddr ir)
    {

        while (1)
        {
            char buff[1024];
            int n = read(sd, buff, sizeof(buff));

            if (n > 0)
            {
                buff[n] = 0;
                string res = _func(buff, ir);
                use_log(loglevel::DEBUG) << ir.get_userinfo() << " say:" << buff;

                write(sd, res.c_str(), res.size());
            }
            else if (n == 0)
            {
                // 读到文件结尾/客户端退出会发送类似文件结尾的标志
                use_log(loglevel::DEBUG) << ir.get_userinfo() << " exit! ";
                close(sd);
                break;
            }
            else
            {
                use_log(loglevel::DEBUG) << ir.get_userinfo() << " abnormal! ";
                close(sd);
                break;
            }
        }
    }
    // static void* route(void *arg){//静态传指针（要求route函数参数不带this指针；故进行封装相关数据）
    //         tdata*r=static_cast<tdata*>(arg);
    //         r->_rp->service(r->_sockfd,r->_id);
    //         delete r;
    //         return nullptr;
    // }

    // class tdata{//打包数据
    //     public:
    //     tdata(tcpserver *rp,inetaddr id,int k):_rp(rp),_id(id),_sockfd(k){}
    //       inetaddr _id;
    //        int _sockfd;
    //        tcpserver *_rp;
    //       // tcpserver r; 这里就需要走构造函数初始化了

    // };
    void start()
    {
        _isrunning = 1;
        while (_isrunning)
        {
            // 1·接收监听队列的客户：
            sockaddr_in si;
            socklen_t len=sizeof(len);
            int sockfd = accept(_listensockfd, (sockaddr *)&si, &len);//监听队列无用户会阻塞状态
            if (sockfd < 0)
            {
                use_log(loglevel::DEBUG) << " accept  failure!";
                continue;
            }
            use_log(loglevel::DEBUG) << " accept  success!";
            // accept从监听队列拿到对应的客户端；完成对应w+r的缓冲区建立（这里可以默认不存在还没accept时候客户端就发信息了；因为服务端是很快的；
            // 在客户端还没发信息的时候就已经accept了；然后搞好了对应的缓冲区；如果客户端退出connect就会断；此时会向对应的r文件发送文件结尾的标志；会被客户端读到）
            inetaddr ir(si);
            // 2·执行读+执行任务然后返回给客户端：

            // 1·单进程版本：
            // service(sockfd, ir); // r+func+w

            // 2·多进程版本(创建子进程然后子进程之后创建孙子进程；最后子进程直接退出；父进程把它回收接着去accept；
            // 而孙子进程变成孤儿进程被系统领养要么执行service；要么被系统自动回收)：
            // 也可以直接使用信号signal(SIGCHLD,SIG_IGN)
            //    int id=fork();
            //    if(id<0) {
            //  use_log(loglevel::DEBUG) << " fork failure!";
            //    exit(FORK_ERR);
            //    }
            //    else if(id==0){
            //        close( _listensockfd);
            //            int iid=fork();
            //            if(iid==0) service(sockfd, ir); // r+func+w
            //            exit(OK);
            //    }
            //    else {
            //        close(sockfd);
            //       pid_t n= waitpid(id,nullptr,0);
            //       (void)n;
            //    }

            // 多线程版本：

            //     pthread_t t1;
            //     tdata *tr=new tdata(this,ir,sockfd);
            //    pthread_create(&t1,0,route,(void*)tr);
            //    pthread_join(t1,nullptr);

            // 线程池版本：
            //   bind绑定：
            auto *tr = Threadpool<task_t>::getinstance();

            auto task = bind(&tcpserver::service, this, sockfd, ir); // bind对于类内成员函数一般&一下
            tr->equeue(task);
        
            // lambda：
            // auto*tr=Threadpool<task_t>::getinstance();

            // tr->equeue([&](){this->service(sockfd,ir);});
        }
        _isrunning = 0;
    }
    ~tcpserver() {}

private:
    uint16_t _port;
    int _listensockfd;
    func_t _func;
    bool _isrunning;
};